// TestDriver.cs
//
// Copyright (c) 2007 Mike Strobel
//
// This source code is subject to the terms of the Microsoft Reciprocal License (Ms-RL).
// For details, see <http://www.opensource.org/licenses/ms-rl.html>.
//
// All other rights reserved.

//#define ASTAR_TEST

using System;
using System.Diagnostics;
using System.Linq.Dynamic;
using System.Linq.Expressions;
using System.Runtime.CompilerServices;

using Supremacy.AI;
using Supremacy.Buildings;
using Supremacy.Collections;
using Supremacy.Economy;
using Supremacy.Effects;
using Supremacy.Game;

using System.Collections.Generic;

using Supremacy.Scripting;
using Supremacy.Types;
using Supremacy.Universe;
using Supremacy.Utility;

using DynamicExpression = System.Linq.Dynamic.DynamicExpression;

namespace Supremacy
{
    public class TestDriver
    {
        [MethodImpl(MethodImplOptions.NoOptimization)]
        [STAThread]
        static void Main()
        {
            var visibilityManger = new ObjectVisibilityManager();
            
            visibilityManger.AddVisibility(
                1,
                1000,
                UniverseObjectVisibility.ExistenceKnown,
                3);

            visibilityManger.AddPermanentVisibility(
                1,
                1000,
                UniverseObjectVisibility.DetailsKnown);

            var gameEngine = new GameEngine();

            Environment.CurrentDirectory = Environment.ExpandEnvironmentVariables(
                @"%USERPROFILE%\Workspace\Supremacy\Mainline\SupremacyClient\bin\Debug");
            AppDomain.CurrentDomain.SetData("DataDirectory", Environment.CurrentDirectory);
            
            var players = new CollectionBase<Player>();

            var game = GameContext.Create(GameOptionsManager.LoadDefaults(), false);

            PlayerContext.Current = new PlayerContext(players);
            GameContext.Push(game);
            try
            {
                var localPlayer = new Player
                                  {
                                      EmpireID = 0,
                                      PlayerID = 0,
                                      Name = "TestDriver"
                                  };

                players.Add(localPlayer);

                gameEngine.DoPreGameSetup(GameContext.Current);

                InitEffects(game);

/*
                var design = GameContext.Current.TechDatabase["FED_SHIPYARD_II"] as BuildingDesign;
                var action = new InitialProductionAction(GameContext.Current.CivilizationManagers[0].HomeColony);
                var stage = new BuildSequenceStage
                            {
                                FinalAction = action,
                                ImmediateTarget = design,
                                UltimateTarget = design
                            };

                var stopwatch = new Stopwatch();
                stopwatch.Start();
                var plan = BuildSequenceStage.GeneratePlan(stage);
                stopwatch.Stop();
                Console.WriteLine(stopwatch.Elapsed);
*/
                var parameters = new[]
                                 {
                                     Expression.Parameter(typeof(Colony), "Source"),
                                     Expression.Parameter(typeof(UniverseObjectSet), "$universe")
                                 };
                var colony = GameContext.Current.CivilizationManagers["FEDERATION"].HomeColony;
                var expr = DynamicExpression.ParseLambda(
                    parameters,
                    typeof(object),
                    "$universe.Where((o, i) => o is Colony).Where((o, i) => i == 0).Select(o => (Colony)o)");

                var result = expr.Compile().DynamicInvoke(colony, GameContext.Current.Universe.Objects);

                colony.GetValue(Colony.TotalEnergyProperty).BaseValue = 1337;

                var clone = Cloneable.Clone(colony);

                Console.WriteLine(colony.TotalEnergy);
                Console.WriteLine(clone.TotalEnergy);
            }
            finally
            {
                GameContext.CheckAndPop(game);
            }
        }

        private static void InitEffects(GameContext game)
        {
            var windTurbines = (BuildingDesign)game.TechDatabase["WIND_TURBINES"];

            var amountParameter = new EffectParameter("#amount", typeof(int));
            var effects = new Effect[]
                          {
                              new SetPropertyEffect(Colony.TotalEnergyProperty, "$baseValue + #amount")
                              {
                                  DescriptionExpression = "\"+{#amount} Energy\""
                              }
                          };

            var effectsGroup = EffectGroup.Create(
                typeof(Building),
                new EffectActivation("\"Online\"", "$source.IsActive"),
                new EffectScope("\"Local System\"", "$source.Sector.System.Colony"),
                new ArrayWrapper<Effect>(effects),
                new EffectParameterBindingCollection(new EffectParameterBinding(amountParameter, 75)));
                               //{
                               //    Activation = new EffectActivationDescriptor
                               //                 {
                               //                     ExpressionText = "$source.IsActive",
                               //                     Description = "Online"
                               //                 },
                               //    Scope = new EffectScopeDescriptor
                               //            {
                               //                SelectorText = "$source.Sector.System.Colony",
                               //                Description = "Local System"
                               //            },
                               //    Effects =
                               //        {
                               //            new SetPropertyEffectDescriptor
                               //            {
                               //                TargetProperty = Colony.TotalEnergyProperty,
                               //                Description = "+{$Amount} Total Energy",
                               //                Parameters = new EffectParameters(new[] { new EffectParameter("$Amount", typeof(int)) }),
                               //                ValueExpression = "$baseValue + $Amount"
                               //            }
                               //        }
                               //};

            //var groupInstance = effectsGroup.CreateInstance(typeof(Building));
            //groupInstance.Effects[0].Parameters = new RuntimeEffectParameters(new[] { new RuntimeEffectParameter(effectsGroup.Effects[0].Parameters[0], 75) });

            windTurbines.Effects.Add(effectsGroup);

            var civManager = game.CivilizationManagers["FEDERATION"];
            windTurbines.TrySpawn(civManager.HomeColony.Location, civManager.Civilization);

            EffectSystem.EnableEffects();
            var totalEnergy = civManager.HomeColony.TotalEnergy;
            Console.WriteLine(totalEnergy);

            civManager.HomeColony.DeactivateBuilding(civManager.HomeColony.Buildings[0]);
            totalEnergy = civManager.HomeColony.TotalEnergy;
            Console.WriteLine(totalEnergy);

            civManager.HomeColony.ActivateBuilding(civManager.HomeColony.Buildings[0]);
            totalEnergy = civManager.HomeColony.TotalEnergy;
            Console.WriteLine(totalEnergy);

            civManager.HomeColony.DeactivateBuilding(civManager.HomeColony.Buildings[0]);
            totalEnergy = civManager.HomeColony.TotalEnergy;
            Console.WriteLine(totalEnergy);

            civManager.HomeColony.ActivateBuilding(civManager.HomeColony.Buildings[0]);
            totalEnergy = civManager.HomeColony.TotalEnergy;
            Console.WriteLine(totalEnergy);
            //windTurbines.Effects.Add();
        }
    }
}
